﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

namespace ZL_Framework
{
    /// <summary>
    /// Lua脚本中模拟Unity的生命周期
    /// </summary>
    public class LuaBehaviour : MonoBehaviour
    {
        public string luaScriptName;
        public Injection[] injections;

        protected Action luaAwake = null;
        protected Action luaStart = null;
        protected Action luaOnEnable = null;
        protected Action luaOnDisable = null;
        protected Action luaUpdate = null;
        protected Action luaFixedUpdate = null;
        protected Action luaLateUpdate = null;
        protected Action luaOnDestroy = null;
        protected LuaTable scriptEnv = null;

        public virtual void Awake()
        {
            if (!string.IsNullOrEmpty(luaScriptName))
            {
                Init(luaScriptName);
            }
        }

        public virtual void Init(string scriptName)
        {
            scriptEnv = LuaManager.Instance.Luaenv.NewTable();
            LuaTable meta = LuaManager.Instance.Luaenv.NewTable();
            meta.Set("__index", LuaManager.Instance.Luaenv.Global);
            scriptEnv.SetMetaTable(meta);
            meta.Dispose();

            LuaManager.Instance.Luaenv.DoString("require " + "'" + scriptName + "'", "LuaComponent", scriptEnv);
            scriptEnv.SetInPath(scriptName + ".self", this);
            luaAwake = scriptEnv.GetInPath<Action>(scriptName + ".awake");
            luaStart = scriptEnv.GetInPath<Action>(scriptName + ".start");
            luaOnEnable = scriptEnv.GetInPath<Action>(scriptName + ".onEnable");
            luaOnDisable = scriptEnv.GetInPath<Action>(scriptName + ".onDisable");
            luaUpdate = scriptEnv.GetInPath<Action>(scriptName + ".update");
            luaFixedUpdate = scriptEnv.GetInPath<Action>(scriptName + ".fixedUpdate");
            luaOnDestroy = scriptEnv.GetInPath<Action>(scriptName + ".onDestroy");
            luaLateUpdate = scriptEnv.GetInPath<Action>(scriptName + ".lateUpdate");

            //通过unity编辑器给lua脚本传递游戏场景物体
            if (injections != null)
            {
                foreach (var injection in injections)
                {
                    scriptEnv.SetInPath(scriptName + "." + injection.name, injection.value);
                }
            }
            scriptEnv.SetInPath(scriptName + ".gameObject", gameObject);
            scriptEnv.SetInPath(scriptName + ".transform", transform);

            luaAwake?.Invoke();
        }

        public virtual void Start()
        {
            luaStart?.Invoke();
        }

        public virtual void OnEnable()
        {
            luaOnEnable?.Invoke();
        }

        public virtual void OnDisable()
        {
            luaOnDisable?.Invoke();
        }

        public virtual void Update()
        {
            luaUpdate?.Invoke();
        }

        public virtual void FixedUpdate()
        {
            luaFixedUpdate?.Invoke();
        }

        public virtual void LateUpdate()
        {
            luaLateUpdate?.Invoke();
        }

        public virtual void OnDestroy()
        {
            luaOnDestroy?.Invoke();

            luaAwake = null;
            luaStart = null;
            luaUpdate = null;
            luaOnEnable = null;
            luaOnDisable = null;
            luaFixedUpdate = null;
            luaLateUpdate = null;
            luaOnDestroy = null;
            injections = null;
            scriptEnv?.Dispose();
        }
    }
}